import java.util.Hashtable;
import java.util.*;

public class Env
{
	Hstack scope=null;
	Env parent_env = null; //for activation records
	
	public Env()
	{
		scope = null;
		parent_env= null;
		
	}
	public void enter_scope()
	{
		Hstack temp=scope;
		scope=new Hstack();
		scope.outer=temp;
	}
	public void leave_scope()
	{
		if(scope.get_outer()!=null)
			scope.set_p_scope(scope.get_outer().get_p_scope());
	}
	
	//takes ID name and type String as its value
	public void add_or_modify(String s, String i)
	{
		String t;
		Hstack temp=scope;
		t=(String)temp.get_variable(s);
		while(t==null && temp.outer != null)
		{
			temp=temp.get_outer();
			t=(String)temp.get_variable(s);
		}
		if(t==null && temp.outer == null)
		{
			t=i;
			
			scope.add_or_modify_variable(s, t);
		}
		t=i;
		
		temp.add_or_modify_variable(s, t);
	}
	
	//takes ID name and type Element as its value
	public void add_or_modify(String s, Element i)
	{
		String t;
		Hstack temp=scope;
		t=(String)temp.get_variable(s);
		while(t==null && temp.outer != null)
		{
			temp=temp.get_outer();
			t=(String)temp.get_variable(s);
		}
		if(t==null && temp.outer == null)
		{				
			scope.add_or_modify_variable(s, i);
		}
		
		temp.add_or_modify_variable(s, i);
	}
	
	//takes ID name and the arraylist as values
	public void add_or_modify(String s, ArrayList<String> i)
	{
		String t;
		Hstack temp=scope;
		t=(String)temp.get_variable(s);
		while(t==null && temp.outer != null)
		{
			temp=temp.get_outer();
			t=(String)temp.get_variable(s);
		}
		if(t==null && temp.outer == null)
		{				
			scope.add_or_modify_variable(s, i);
		}
		
		temp.add_or_modify_variable(s, i);
	}
	
	//TODO for all others methods override them to tke arraylist also

	//takes ID name and type ArrayList as its value
	public void add_in_present_scope(String s, ArrayList<String> i)
	{
		ArrayList<String> t=i;
	
		scope.add_or_modify_variable(s, t);
	}

	//takes ID name and type String as its value
	public void add_in_present_scope(String s, String i)
	{
		String t=i;
	
		scope.add_or_modify_variable(s, t);
	}
	
	//takes ID name and type Element as its value
	public void add_in_present_scope(String s, Element i)
	{
		scope.add_or_modify_variable(s, i);
	}
	
	
	public boolean check_in_present_scope(String s)
	{
		if(scope.get_variable(s)!=null)
			return true;
		else
			return false;
	}
	

	
	public Object get_variable(String s)
	{
		Object t;
		t=scope.get_variable(s);
		Hstack temp=scope.get_outer();
		while(t==null && temp != null)
		{
			t=temp.get_variable(s);
			temp=temp.get_outer();
		}
		return t;
	}
	
}